#============================================================
#	Set Collision By Name
#============================================================
#  根据 ProjectSetting 中的 layer_names/2d_physics 中的名称设置
# 父节点的 collision_mask 属性
#============================================================
# @datetime: 2022-5-15 23:37:46
#============================================================
extends Node
class_name CollisionByName


const META_PHYSICS_LAYER_KEY = "meta_physics_layer_data"


export var debug_info : bool = false
export var layer_names : PoolStringArray = [] setget set_layer_names
export var mask_names : PoolStringArray = [] setget set_mask_names

var _layer_data : Dictionary = {}


#============================================================
#   Set/Get
#============================================================
func set_layer_names(value: PoolStringArray) -> void:
	layer_names = value
	if is_inside_tree():
		update_collision()

func set_mask_names(value: PoolStringArray) -> void:
	mask_names = value
	if is_inside_tree():
		update_collision()


#============================================================
#   内置
#============================================================
func _enter_tree():
	# 通过设置获取 root 元数据的方式，作为单例数据
	var root = get_tree().root
	if not root.has_meta(META_PHYSICS_LAYER_KEY):
		# 默认 32 层
		for i in range(1, 32+1):
			var l_name : String = ProjectSettings.get("layer_names/2d_physics/layer_%d" % i)
			if l_name != "":
				# 这个名称的碰撞层的值
				_layer_data[l_name] = 1 << (i - 1)
		root.set_meta(META_PHYSICS_LAYER_KEY, _layer_data)
	
	_layer_data = root.get_meta(META_PHYSICS_LAYER_KEY)


func _ready():
	
	if not (get_parent() is CollisionObject2D 
			or get_parent() is TileMap
			or get_parent() is RayCast2D
	):
		# 输出所在场景的位置
		printt(get_parent(), owner.filename)
		assert(false, "父节点必须是 TileMap、CollisionObject2D 或其子类型！")
		
	update_collision()


#============================================================
#   自定义
#============================================================
##  更新 Collision 
func update_collision():
	var p = get_parent()
	
	var collision_layer = 0
	var collision_mask = 0
	
	# 碰撞层
	if not get_parent() is RayCast2D:
		for layer_name in layer_names:
			if _layer_data.has(layer_name):
				collision_layer |= _layer_data[layer_name]
			else:
				Logger.info(self, ["没有 ", layer_name, " 这个名称的碰撞层"])
		p.collision_layer = collision_layer
	
	# 碰撞掩码
	for layer_name in mask_names:
		if _layer_data.has(layer_name):
			collision_mask |= _layer_data[layer_name]
		else:
			Logger.info(self, ["没有 ", layer_name, " 这个名称的碰撞层"])
	p.collision_mask = collision_mask
	
	if debug_info and (collision_layer != 0 || collision_mask != 0):
		Logger.info(self, ["已重新设置 ", p, " 的碰撞属性"])
